/**
 * AnimatedBottomModal - 从底部弹出的动画模态框组件
 *
 * 功能特性：
 * - 从底部向上弹出动画
 * - 高度由子组件自动决定
 * - 支持点击遮罩层关闭
 * - 支持向下滑动手势关闭
 * - 可自定义动画时长和样式
 * - 完整的 TypeScript 类型支持
 * - 支持命令式控制（通过 ref 调用 show/hide）
 */

import React, {
  useEffect,
  useRef,
  useState,
  forwardRef,
  useImperativeHandle,
} from 'react';
import {
  View,
  StyleSheet,
  Modal,
  Animated,
  TouchableWithoutFeedback,
  Dimensions,
  PanResponder,
  LayoutChangeEvent,
} from 'react-native';

const SCREEN_HEIGHT = Dimensions.get('window').height;

// ==================== 类型定义 ====================

export interface AnimatedBottomModalProps {
  /** 是否显示模态框（可选，如果使用 ref 控制则不需要） */
  visible?: boolean;
  /** 关闭回调（可选） */
  onClose?: () => void;
  /** 子组件 */
  children: React.ReactNode;
  /** 动画时长（毫秒），默认 300 */
  animationDuration?: number;
  /** 是否启用点击遮罩关闭，默认 true */
  closeOnOverlayTap?: boolean;
  /** 是否启用下滑关闭，默认 true */
  closeOnSwipeDown?: boolean;
  /** 模态框容器样式 */
  containerStyle?: object;
  /** 遮罩层样式 */
  overlayStyle?: object;
  /** 是否显示顶部拖动条，默认 true */
  showDragIndicator?: boolean;
  /** 拖动条样式 */
  dragIndicatorStyle?: object;
  /** 触发关闭的最小下滑距离，默认 50 */
  swipeThreshold?: number;
}

/**
 * 命令式控制接口
 */
export interface AnimatedBottomModalRef {
  /** 显示模态框 */
  show: () => void;
  /** 隐藏模态框 */
  hide: () => void;
}

// ==================== 主组件 ====================

export const AnimatedBottomModal = forwardRef<
  AnimatedBottomModalRef,
  AnimatedBottomModalProps
>(
  (
    {
      visible,
      onClose,
      children,
      animationDuration = 300,
      closeOnOverlayTap = true,
      closeOnSwipeDown = true,
      containerStyle,
      overlayStyle,
      showDragIndicator = true,
      dragIndicatorStyle,
      swipeThreshold = 50,
    },
    ref,
  ) => {
    // ==================== 状态管理 ====================

    // 内部状态：用于 ref 控制方式
    const [internalVisible, setInternalVisible] = useState(false);
    // 实际的可见状态：优先使用 visible prop，如果没有则使用内部状态
    const isVisible = visible !== undefined ? visible : internalVisible;

    // 控制 Modal 组件的显示/隐藏（延迟卸载，等动画完成）
    const [modalVisible, setModalVisible] = useState(false);
    // 存储模态框内容的高度
    const [contentHeight, setContentHeight] = useState(0);

    // 动画值：控制从底部滑入/滑出
    const translateY = useRef(new Animated.Value(SCREEN_HEIGHT)).current;
    // 动画值：控制遮罩层透明度
    const overlayOpacity = useRef(new Animated.Value(0)).current;

    // ==================== 命令式接口 ====================

    // 暴露给父组件的方法
    useImperativeHandle(ref, () => ({
      show: () => {
        setInternalVisible(true);
      },
      hide: () => {
        setInternalVisible(false);
      },
    }));

    // ==================== 手势处理 ====================

    const panResponder = useRef(
      PanResponder.create({
        onStartShouldSetPanResponder: () => closeOnSwipeDown,
        onMoveShouldSetPanResponder: (_, gestureState) => {
          // 只有向下滑动时才响应
          return closeOnSwipeDown && gestureState.dy > 5;
        },
        onPanResponderMove: (_, gestureState) => {
          // 只允许向下滑动
          if (gestureState.dy > 0) {
            translateY.setValue(gestureState.dy);
          }
        },
        onPanResponderRelease: (_, gestureState) => {
          if (gestureState.dy > swipeThreshold) {
            // 滑动距离超过阈值，关闭模态框
            handleClose();
          } else {
            // 滑动距离不够，回弹
            Animated.spring(translateY, {
              toValue: 0,
              useNativeDriver: true,
              tension: 50,
              friction: 8,
            }).start();
          }
        },
      }),
    ).current;

    // ==================== 事件处理 ====================

    const handleClose = () => {
      // 如果使用 ref 控制，更新内部状态
      if (visible === undefined) {
        setInternalVisible(false);
      }
      // 调用关闭回调（如果提供）
      onClose?.();
    };

    const handleOverlayPress = () => {
      if (closeOnOverlayTap) {
        handleClose();
      }
    };

    const handleContentLayout = (event: LayoutChangeEvent) => {
      const { height } = event.nativeEvent.layout;
      setContentHeight(height);
    };

    // ==================== 副作用 ====================

    useEffect(() => {
      console.log(
        'useEffect isVisible',
        isVisible,
        'modalVisible',
        modalVisible,
      );
      if (isVisible === true && modalVisible === false) {
        // 打开时：先设置 Modal 可见，然后执行动画
        setModalVisible(true);
        // 需要在下一帧执行动画，确保 Modal 已经渲染
        requestAnimationFrame(() => {
          Animated.parallel([
            Animated.timing(translateY, {
              toValue: 0,
              duration: animationDuration,
              useNativeDriver: true,
            }),
            Animated.timing(overlayOpacity, {
              toValue: 1,
              duration: animationDuration,
              useNativeDriver: true,
            }),
          ]).start();
        });
      } else if (isVisible === false && modalVisible === true) {
        // 关闭时：先执行动画，动画结束后再隐藏 Modal
        Animated.parallel([
          Animated.timing(translateY, {
            toValue: contentHeight || SCREEN_HEIGHT,
            duration: animationDuration,
            useNativeDriver: true,
          }),
          Animated.timing(overlayOpacity, {
            toValue: 0,
            duration: animationDuration,
            useNativeDriver: true,
          }),
        ]).start(() => {
          setModalVisible(false);
        });
      }
    }, [
      animationDuration,
      contentHeight,
      isVisible,
      modalVisible,
      overlayOpacity,
      translateY,
    ]);

    // 初始化动画值
    useEffect(() => {
      translateY.setValue(SCREEN_HEIGHT);
      overlayOpacity.setValue(0);
    }, [overlayOpacity, translateY]);

    // ==================== 渲染 ====================

    return (
      <Modal
        transparent
        visible={modalVisible}
        onRequestClose={handleClose}
        statusBarTranslucent
        animationType="none" // 使用自定义动画
      >
        <View style={styles.modalContainer}>
          {/* 遮罩层 */}
          <TouchableWithoutFeedback onPress={handleOverlayPress}>
            <Animated.View
              style={[
                styles.overlay,
                overlayStyle,
                { opacity: overlayOpacity },
              ]}
            />
          </TouchableWithoutFeedback>

          {/* 模态框内容 */}
          <Animated.View
            style={[
              styles.contentContainer,
              containerStyle,
              {
                transform: [{ translateY }],
              },
            ]}
            onLayout={handleContentLayout}
            {...(closeOnSwipeDown ? panResponder.panHandlers : {})}
          >
            {/* 拖动指示器 */}
            {showDragIndicator && (
              <View style={styles.dragIndicatorContainer}>
                <View style={[styles.dragIndicator, dragIndicatorStyle]} />
              </View>
            )}

            {/* 子组件内容 */}
            {children}
          </Animated.View>
        </View>
      </Modal>
    );
  },
);

// 设置 displayName 便于调试
AnimatedBottomModal.displayName = 'AnimatedBottomModal';

// ==================== 样式定义 ====================

const styles = StyleSheet.create({
  modalContainer: {
    flex: 1,
    justifyContent: 'flex-end',
  },
  overlay: {
    ...StyleSheet.absoluteFillObject,
    backgroundColor: 'rgba(0, 0, 0, 0.5)',
  },
  contentContainer: {
    backgroundColor: '#FFFFFF',
    borderTopLeftRadius: 20,
    borderTopRightRadius: 20,
    paddingBottom: 20,
    maxHeight: SCREEN_HEIGHT * 0.9, // 最大高度为屏幕的 90%
    // iOS 阴影
    shadowColor: '#000',
    shadowOffset: {
      width: 0,
      height: -2,
    },
    shadowOpacity: 0.25,
    shadowRadius: 10,
    // Android 阴影
    elevation: 5,
  },
  dragIndicatorContainer: {
    alignItems: 'center',
    paddingVertical: 12,
  },
  dragIndicator: {
    width: 40,
    height: 4,
    backgroundColor: '#CCCCCC',
    borderRadius: 2,
  },
});
